using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
namespace Cliente
{
	class MainClass
	{
	

	    public static void StartClient() {
        	byte[] bytes = new byte[1024];
        	try {
            	IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("192.168.0.137"),5050);
    	        Socket sender = new Socket(AddressFamily.InterNetwork, 
        	        SocketType.Stream, ProtocolType.Tcp );
            	try {
                	sender.Connect(remoteEP);

	                Console.WriteLine("Socket connected to {0}",
    	                sender.RemoteEndPoint.ToString());

                	
					//Recibe Bienvenida del servidor
					byte[] recibido = Recibir(sender); //recibir
					//deserializar el mensaje XML
					Stream st       = new MemoryStream(recibido);
					Mensaje msg     = Mensaje.Deserialize(st);
					String content  = Encoding.UTF8.GetString(recibido);
					st.Close();
					Console.WriteLine(content);
					//Serializar el mensaje XML creando el archivo recibido+id.xml
					Mensaje m = new Mensaje();
					m.contenido = msg.contenido;
					m.clientID = msg.clientID;
					m.tipo     = msg.tipo;
					m.RSerialize();
					
					Console.WriteLine("Recibido");
					
					//Enviar
					
					//Creando mensaje a enviar - Comando LIST
					Mensaje mensaje = new Mensaje();
					mensaje.contenido = "List"; //id del video
					mensaje.tipo      = Mensaje.MsgType.LIST;
					mensaje.clientID  = msg.clientID;					
					mensaje.Serialize();//Serializar el mensaje
					
					SendMsg(sender,mensaje);//Enviar mensaje al servidor		
					Console.WriteLine("Enviado Solicitud Video");
					
					//Recibiendo el listado
					recibido = Recibir(sender);
					FileStream fs = new FileStream(Directory.GetCurrentDirectory()+"/xml/listado.xml",FileMode.Create);
					fs.Write(recibido,0,recibido.Length);
					fs.Close();
					List<VideoList> listado = DeserializeList(Directory.GetCurrentDirectory()+"/xml/listado.xml",msg.clientID);
					foreach(VideoList video in listado){
						video.show();
					}
					//Finalizar coneccion se eliminan los archivos del directorio xml/
					foreach(string f in Directory.GetFiles(Directory.GetCurrentDirectory()+"/xml/")){
							File.Delete(f);
					}
					
					//Creando mensaje a enviar - Comando VIDEO
					mensaje = new Mensaje();
					mensaje.contenido = "1"; //id del video
					mensaje.tipo      = Mensaje.MsgType.VIDEO;
					mensaje.clientID  = msg.clientID;					
					mensaje.Serialize();//Serializar el mensaje
					
					SendMsg(sender,mensaje);//Enviar mensaje al servidor		
					Console.WriteLine("Enviado Solicitud Video");
					//Recibir el video
					recibido = Recibir(sender);
					fs = new FileStream(Directory.GetCurrentDirectory()+"/video.3gp",FileMode.Create);
					BinaryWriter bw = new BinaryWriter(fs);
					bw.Write(recibido);
					bw.Close();
					Console.WriteLine("Video recibido");
					
                	// Release the socket.
	                sender.Shutdown(SocketShutdown.Both);
    	            sender.Close();
                
            	} catch (ArgumentNullException ane) {
	                Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
    	        } catch (SocketException se) {
        	        Console.WriteLine("SocketException : {0}",se.ToString());
            	} catch (Exception e) {
                	Console.WriteLine("Unexpected exception : {0}", e.ToString());
            	}

        	} catch (Exception e) {
            	Console.WriteLine( e.ToString());
        	}
    	}
		
		private static byte[] ReadFully (Stream stream){
			int initialLength = 1024;
    		byte[] buffer = new byte[initialLength];
    		int read=0;
    		int chunk;
    		while ( (chunk = stream.Read(buffer, read, buffer.Length-read)) > 0){
        		read += chunk;
				if (read == buffer.Length){
            		int nextByte = stream.ReadByte();
        		    if (nextByte==-1){
                		return buffer;
            		}
                    byte[] newBuffer = new byte[buffer.Length*2];
            		Array.Copy(buffer, newBuffer, buffer.Length);
            		newBuffer[read]=(byte)nextByte;
            		buffer = newBuffer;
            		read++;
        		}
    		}
			byte[] ret = new byte[read];
    		Array.Copy(buffer, ret, read);
    		return ret;
		}
		
		private static void SendMsg(Socket socket, Mensaje mensaje){
			mensaje.Serialize();
			
			FileStream fs = new FileStream(mensaje.getFile(),FileMode.Open,FileAccess.Read,FileShare.Read);
			byte[] video = ReadFully(fs);
			int total = 0;
			int size = video.Length;				
			int dataleft = size;
			int sent;
			
			byte[] datasize = new byte[4];
			datasize        = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(size));
			sent            = socket.Send(datasize);
			while(total < size){
				sent  = socket.Send(video,total,dataleft,SocketFlags.None);
				total+= sent;
				dataleft-= sent;
			}
		}

		private static byte[] Recibir(Socket s){
			int total = 0;
            int recv;
            byte[] datasize = new byte[4];
			
            recv = s.Receive(datasize, 0, 4, 0);
			int size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(datasize, 0));
			
            int dataleft = size;
            byte[] data = new byte[size];
            while (total < size)
            {
                recv = s.Receive(data, total, dataleft, 0);
                if (recv == 0)
                {
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
        }
		
		
		/* Metodo para deserializar un archivo XML de tipo Listado de video*/
		private static List<VideoList> DeserializeList(String archivo, Guid id){
   			XmlSerializer deserializer = new XmlSerializer(typeof(List<VideoList>));
   			TextReader textReader = new StreamReader(archivo);
   			List<VideoList> listado  = (List<VideoList>)deserializer.Deserialize(textReader);
   			textReader.Close();	
   			return listado;
		}//DeserializeList
		

		

					
		public static void Main (string[] args)
		{
			MainClass.StartClient();
		}
	}
}

